/**
 * SlideDeck 1.1.7 Lite - 2010-07-18
 * Copyright (c) 2010 digital-telepathy (http://www.dtelepathy.com)
 * 
 * Support the developers by purchasing the Pro version at http://www.slidedeck.com/download
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * More information on this project:
 * http://www.slidedeck.com/
 * 
 * Requires: jQuery v1.3+
 * 
 * Full Usage Documentation: http://www.slidedeck.com/usage-documentation 
 * Usage:
 *     $(el).slidedeck(opts);
 * 
 * @param {HTMLObject} el	The <DL> element to extend as a SlideDeck
 * @param {Object} opts		An object to pass custom override options to
 */

var SlideDeck;

(function($){
	SlideDeck = function(el,opts){
		var self = this,
			el = $(el);
		
        var VERSION = "1.1.6";
        
		this.options = {
			speed: 500,
			transition: 'swing',
			start: 1,
			activeCorner: true,
			index: true,
			scroll: true,
			keys: true,
			autoPlay: false,
			autoPlayInterval: 5000,
			hideSpines: false,
			cycle: false
		};
		
		this.classes = {
			slide: 'slide',
			spine: 'spine',
			label: 'label',
			index: 'index',
			active: 'active',
			indicator: 'indicator',
			activeCorner: 'activeCorner',
			disabled: 'disabled',
            vertical: 'slidesVertical',
            previous: 'previous',
            next: 'next'
		};
		
		this.current = 1;
		this.deck = el;
		this.spines = el.find('dt');
		this.slides = el.find('dd');
		this.controlTo = 1;
		this.session = [];
		this.disabledSlides = [];
		this.pauseAutoPlay = false;
        this.isLoaded = false;
        
		var UA = navigator.userAgent.toLowerCase();
		this.browser = {
			chrome: UA.match(/chrome/) ? true : false,
			firefox: UA.match(/firefox/) ? true : false,
			firefox2: UA.match(/firefox\/2/) ? true : false,
			firefox30: UA.match(/firefox\/3\.0/) ? true : false,
			msie: UA.match(/msie/) ? true : false,
			msie6: (UA.match(/msie 6/) && !UA.match(/msie 7|8/)) ? true : false,
			msie7: UA.match(/msie 7/) ? true : false,
			msie8: UA.match(/msie 8/) ? true : false,
            chromeFrame: (UA.match(/msie/) && UA.match(/chrome/)) ? true : false,
			opera: UA.match(/opera/) ? true : false,
			safari: (UA.match(/safari/) && !UA.match(/chrome/)) ? true : false
		};
		for(var b in this.browser){
			if(this.browser[b] === true){
				this.browser._this = b;
			}
		}
		if(this.browser.chrome === true) {
			this.browser.version = UA.match(/chrome\/([0-9\.]+)/)[1];
		}
		if(this.browser.firefox === true) {
			this.browser.version = UA.match(/firefox\/([0-9\.]+)/)[1];
		}
		if(this.browser.msie === true) {
			this.browser.version = UA.match(/msie ([0-9\.]+)/)[1];
		}
		if(this.browser.opera === true) {
			this.browser.version = UA.match(/version\/([0-9\.]+)/)[1];
		}
		if(this.browser.safari === true) {
			this.browser.version = UA.match(/version\/([0-9\.]+)/)[1];
		}
		
		var width;
		var height;

		var spine_inner_width,
			spine_outer_width,
			slide_width,
			spine_half_width;
		
		var FixIEAA = function(spine){
			if(self.browser.msie && !self.browser.chromeFrame){
				var bgColor = spine.css('background-color');
				var sBgColor = bgColor;
				if(sBgColor == "transparent"){
					bgColor = "#ffffff";
				} else {
					if(sBgColor.match('#')){
						// Hex, convert to RGB
						if(sBgColor.length < 7){
							var t = "#" + sBgColor.substr(1,1) + sBgColor.substr(1,1) + sBgColor.substr(2,1) + sBgColor.substr(2,1) + sBgColor.substr(3,1) + sBgColor.substr(3,1);
							bgColor = t;
						}
					}
				}
				bgColor = bgColor.replace("#","");
				cParts = {
					r: bgColor.substr(0,2),
					g: bgColor.substr(2,2),
					b: bgColor.substr(4,2)
				};
				var bgRGB = "#";
				var hexVal = "01234567890ABCDEF";
				for(var k in cParts){
					cParts[k] = Math.max(0,(parseInt(cParts[k],16) - 1));
					cParts[k] = hexVal.charAt((cParts[k] - cParts[k]%16)/16) + hexVal.charAt(cParts[k]%16);
					
					bgRGB += cParts[k];
				}
				
				spine.find('.' + self.classes.index).css({
					'filter': 'progid:DXImageTransform.Microsoft.BasicImage(rotation=1) chroma(color=' + bgRGB + ')',
					backgroundColor: bgRGB
				});
			}
		};
		
		
        /**
         * Visual Attribution "Bug"
         * 
         * This is a visual "bug" that is placed in the lower right of the SlideDeck to give
         * visual recognition to SlideDeck and for us to see where any implementations that might
         * be worth placing in our community examples page reside. To help keep this plugin free 
         * we ask (although we cannot force) you to keep this visual "bug" on the page since it 
         * helps support the author.
         * 
         * If you would like to remove the visual "bug", we recommend you comment out the 
         * updateBug(); function and remove any references to the updateBug(); command.
         */
		var BUG = {
			id: "SlideDeck_Bug"+(Math.round(Math.random()*100000000)),
			styles: "position:absolute !important;height:"+13+"px !important;width:"+130+"px !important;display:block !important;margin:0 !important;overflow:hidden !important;visibility:visible !important;opacity:1 !important;padding:0 !important;z-index:20000 !important",
			width: 130,
			height: 13
		};		
		var updateBug = function(){
			if(!document.getElementById(BUG.id)){
				var bugLink = document.createElement('A');
					bugLink.id = BUG.id;
					bugLink.href = "http://www.slidedeck.com/?ref=" + document.location.hostname;
					bugLink.target = "_blank";
				var bugImg = document.createElement('IMG');
					bugImg.src = (document.location.protocol == "https:" ? "https:" : "http:") + "//www.slidedeck.com/6885858486f31043e5839c735d99457f045affd0/" + VERSION + "/lite";
					bugImg.alt = "Powered by SlideDeck&trade;";
					bugImg.width = BUG.width;
					bugImg.height = BUG.height;
					bugImg.border = "0";
				bugLink.appendChild(bugImg);
				
				BUG.top = (el.offset().top + el.height() + 5);
				BUG.left = el.offset().left + el.width() - BUG.width;

				var s = document.createElement('STYLE');
					s.type = "text/css";
				var sText = '#' + BUG.id + '{top:' + BUG.top + 'px;left:' + BUG.left + 'px;' + BUG.styles + '}' + '#' + BUG.id + ' img{top:0 !important;left:0 !important;' + BUG.styles + '}';
				if(s.styleSheet){
					s.styleSheet.cssText = sText;
				} else {
					s.appendChild(document.createTextNode(sText));
				}
				$('head').append(s);
				
				if(Math.random() < 0.5){
                    $(document.body).prepend(bugLink);
                } else {
                    $(document.body).append(bugLink);
                }

				$(window).resize(function(){
					updateBug();
				});
			}
			BUG.top = (el.offset().top + el.height() + 5);
			BUG.left = el.offset().left + el.width() - BUG.width;

			$('#' + BUG.id).css({
				top: BUG.top + "px",
				left: BUG.left + "px"
			});
		};
		
		
		var autoPlay = function(){
			gotoNext = function(){
				if(self.pauseAutoPlay === false){
					if(self.options.cycle === false && self.current == self.slides.length){
						self.pauseAutoPlay = true;
					} else {
						self.next();
					}
				}
			};
			
			setInterval(gotoNext,self.options.autoPlayInterval);
		};
		
		
		var buildDeck = function(){
			if($.inArray(el.css('position'),['position','absolute','fixed'])){
				el.css('position', 'relative');
			}
			el.css('overflow', 'hidden');
			for(var i=0; i<self.slides.length; i++){
				var slide = $(self.slides[i]);
				if(self.spines.length > i){
					var spine = $(self.spines[i]);
				}
				var sPad = {
					top: parseInt(slide.css('padding-top'),10),
					right: parseInt(slide.css('padding-right'),10),
					bottom: parseInt(slide.css('padding-bottom'),10),
					left: parseInt(slide.css('padding-left'),10)
				};
				var sBorder = {
					top: parseInt(slide.css('border-top-width'),10),
					right: parseInt(slide.css('border-right-width'),10),
					bottom: parseInt(slide.css('border-bottom-width'),10),
					left: parseInt(slide.css('border-left-width'),10)
				};
				for(var k in sBorder){
					sBorder[k] = isNaN(sBorder[k]) ? 0 : sBorder[k];
				}
				if(i < self.current) {
					if(i == self.current - 1){
						if(self.options.hideSpines !== true){
							spine.addClass(self.classes.active);
						}
						slide.addClass(self.classes.active);
					}
					offset = i * spine_outer_width;
					if(self.options.hideSpines === true){
						offset = 0 - (i * el.width());
					}
				} else {
					offset = i * spine_outer_width + slide_width;
					if(self.options.hideSpines === true){
						offset = i * el.width();
					}
				}
				
                self.slide_width = (slide_width - sPad.left - sPad.right - sBorder.left - sBorder.right);
                
				slide.css({
					position: 'absolute',
					left: offset,
					zIndex: 1,
					height: (height - sPad.top - sPad.bottom - sBorder.top - sBorder.bottom) + "px",
					width: self.slide_width + "px",
					margin: 0,
					paddingLeft: sPad.left + spine_outer_width + "px"
				}).addClass(self.classes.slide).addClass(self.classes.slide + "_" + (i + 1));
				
				if (self.options.hideSpines !== true) {
                    var spinePad = {
    					top: parseInt(spine.css('padding-top'),10),
    					right: parseInt(spine.css('padding-right'),10),
    					bottom: parseInt(spine.css('padding-bottom'),10),
    					left: parseInt(spine.css('padding-left'),10)
                    };
                    for(var k in spinePad) {
                        if(spinePad[k] < 10 && (k == "left" || k == "right")){
                            spinePad[k] = 10;
                        }
                    }
                    var spinePadString = spinePad.top + "px " + spinePad.right + "px " + spinePad.bottom + "px " + spinePad.left + "px";
					spine.css({
						position: 'absolute',
						zIndex: 3,
						display: 'block',
						left: offset,
						width: (height - spinePad.left - spinePad.right) + "px",
						height: spine_inner_width + "px",
						padding: spinePadString,
						rotation: '270deg',
						'-webkit-transform': 'rotate(270deg)',
						'-webkit-transform-origin': spine_half_width + 'px 0px',
						'-moz-transform': 'rotate(270deg)',
						'-moz-transform-origin': spine_half_width + 'px 0px',
						'-o-transform': 'rotate(270deg)',
						'-o-transform-origin': spine_half_width + 'px 0px',
						textAlign: 'right',
						top: (self.browser.msie && !self.browser.chromeFrame) ? 0 : (height - spine_half_width) + "px",
						marginLeft: ((self.browser.msie && !self.browser.chromeFrame) ? 0 : (0 - spine_half_width)) + "px",
						filter: 'progid:DXImageTransform.Microsoft.BasicImage(rotation=3)'
					}).addClass(self.classes.spine).addClass(self.classes.spine + "_" + (i + 1));
				} else {
					if(typeof(spine) != "undefined"){
						spine.hide();
					}
				}
				if(i == self.slides.length-1){
					slide.addClass('last');
					if(self.options.hideSpines !== true){
						spine.addClass('last');
					}
				}
				
				// Add slide active corners
				if(self.options.activeCorner === true && self.options.hideSpines === false){
					var corner = document.createElement('DIV');
						corner.className = self.classes.activeCorner + ' ' + (self.classes.spine + '_' + (i + 1));
					
					spine.after(corner);
					spine.next('.' + self.classes.activeCorner).css({
						position: 'absolute',
						top: '25px',
						left: offset + spine_outer_width + "px",
						overflow: "hidden",
						zIndex: "20000"
					}).hide();
					if(spine.hasClass(self.classes.active)){
						spine.next('.' + self.classes.activeCorner).show();
					}
				}
				
                if (self.options.hideSpines !== true) {
    				// Add spine indexes, will always be numerical if unlicensed
    				var index = document.createElement('DIV');
    					index.className = self.classes.index;
    					
    				if(self.options.index !== false){
    					var textNode;
    					if(typeof(self.options.index) != 'boolean'){
    						textNode = self.options.index[i%self.options.index.length];
    					} else {
    						textNode = "" + (i + 1);
    					}
    					index.appendChild(document.createTextNode(textNode));
    				}
    						
                    spine.append(index);
                    spine.find('.' + self.classes.index).css({
                        position: 'absolute',
                        zIndex: 2,
                        display: 'block',
                        width: spine_inner_width + "px",
                        height: spine_inner_width + "px",
                        textAlign: 'center',
                        bottom: ((self.browser.msie && !self.browser.chromeFrame) ? 0 : (0 - spine_half_width)) + "px",
                        left: ((self.browser.msie && !self.browser.chromeFrame) ? 5 : 20) + "px",
                        rotation: "90deg",
                        '-webkit-transform': 'rotate(90deg)',
                        '-webkit-transform-origin': spine_half_width + 'px 0px',
                        '-moz-transform': 'rotate(90deg)',
                        '-moz-transform-origin': spine_half_width + 'px 0px',
                        '-o-transform': 'rotate(90deg)',
                        '-o-transform-origin': spine_half_width + 'px 0px'
                    });

					FixIEAA(spine);
				}
			}
			
			updateBug();
			
			if(self.options.hideSpines !== true){
				// Setup Click Interaction
				self.spines.bind('click', function(event){
					event.preventDefault();
					self.goTo(self.spines.index(this)+1);
				});
  			}
			
			// Setup Keyboard Interaction
			if(self.options.keys !== false){
				$(document).bind('keydown', function(event){
					if($(event.target).parents().index(self.deck) == -1){
						if(event.keyCode == 39) {
							self.next();
						} else if(event.keyCode == 37) {
							self.prev();
						}
					}
				});
			}
			
			// Setup Mouse Wheel Interaction
			if(typeof($.event.special.mousewheel) != "undefined"){
				el.bind("mousewheel", function(event){
					if(self.options.scroll !== false){
                        var delta = event.detail ? event.detail : event.wheelDelta;
						if(self.browser.msie || self.browser.safari || self.browser.chrome){
							delta = 0 - delta;
						}

						var internal = false;
						if($(event.originalTarget).parents(self.deck).length){
							if($.inArray(event.originalTarget.nodeName.toLowerCase(),['input','select','option','textarea']) != -1){
								internal = true;
							}
						}

						if (internal !== true) {
							if (delta > 0) {
								switch (self.options.scroll) {
									case "stop":
										event.preventDefault();
										break;
									case true:
									default:
										if (self.current < self.slides.length) {
											event.preventDefault();
										}
									break;
								}
								self.next();
							}
							else {
								switch (self.options.scroll) {
									case "stop":
										event.preventDefault();
										break;
									case true:
									default:
										if (self.current != 1) {
											event.preventDefault();
										}
									break;
								}
								self.prev();
							}
						}
					}	
				});
			}
            
            $(self.spines[self.current - 2]).addClass(self.classes.previous);
            $(self.spines[self.current]).addClass(self.classes.next);

			if(self.options.autoPlay === true){
				autoPlay();
			}
            self.isLoaded = true;
		};
		
		
		var getValidSlide = function(ind){
			ind = Math.min(self.slides.length,Math.max(1,ind));
			return ind;
		};


		var slide = function(ind,params){
			ind = getValidSlide(ind);
			
			// Determine if we are moving forward in the SlideDeck or backward, 
			// this is used to determine when the callback should be run
			var forward = true;
			if(ind < self.current){
				forward = false;
			}
			
            var classReset = [self.classes.active, self.classes.next, self.classes.previous].join(' ');
			self.current = ind;
			self.spines.removeClass(classReset);
			self.slides.removeClass(classReset);
			el.find('.' + self.classes.activeCorner).hide();
            
            $(self.spines[self.current - 2]).addClass(self.classes.previous);
            $(self.spines[self.current]).addClass(self.classes.next);
            
			for (var i = 0; i < self.slides.length; i++) {
				var pos = 0;
				if(self.options.hideSpines !== true){
					var spine = $(self.spines[i]);
				}
				var slide = $(self.slides[i]);
				if (i < self.current) {
					if (i == (self.current - 1)) {
						slide.addClass(self.classes.active);
						if(self.options.hideSpines !== true){
							spine.addClass(self.classes.active);
							spine.next('.' + self.classes.activeCorner).show();
						}
					}
					pos = i * spine_outer_width;
				} else {
					pos = i * spine_outer_width + slide_width;
				}
				
				if(self.options.hideSpines === true){
					pos = (i - self.current + 1) * el.width();
				}

				var animOpts = {
					duration: self.options.speed,
					easing: self.options.transition
				};

				slide.stop().animate({
					left: pos + "px",
                    width: self.slide_width + "px"
				}, animOpts);

				if(self.options.hideSpines !== true){
					FixIEAA(spine);
					if(spine.css('left') != pos+"px"){
						spine.stop().animate({
							left: pos + "px"
						},{
							duration: self.options.speed,
							easing: self.options.transition
						});

						spine.next('.' + self.classes.activeCorner).stop().animate({
							left: pos + spine_outer_width + "px"
						},{
							duration: self.options.speed,
							easing: self.options.transition
						});
					}
				}
				
			}
			updateBug();
		};
        
        
        var setOption = function(opts, val){
            var newOpts = opts;
            
            if(typeof(opts) === "string"){
                newOpts = {};
                newOpts[opts] = val;
            }
            
            for(var key in newOpts){
                val = newOpts[key];
                
                switch(key){
                    case "speed":
                    case "start":
                        val = parseFloat(val);
                        if(isNaN(val)){
                            val = self.options[key];
                        }
                    break;                    
                    case "scroll":
                    case "keys":
                    case "activeCorner":
                    case "hideSpines":
                    case "autoPlay":
                    case "cycle":
                        if(typeof(val) !== "boolean"){
                            val = self.options[key];
                        }
                    break;                    
                    case "transition":
                        if(typeof(val) !== "string"){
                            val = self.options[key];
                        }
                    break;
                    case "complete":
                    case "before":
                        if(typeof(val) !== "function"){
                            val = self.options[key];
                        }
                    break;
                    case "index":
                        if(typeof(val) !== "boolean"){
                            if(!$.isArray(val)){
                                val = self.options[key];
                            }
                        }
                    break;                    
                }
                
                self.options[key] = val;
            }
        };
		
		
        var setupDimensions = function(){
    		height = el.height();
    		width = el.width();

            el.css('height', height + "px");
    
    		spine_inner_width = 0;
    		spine_outer_width = 0;

			if(self.options.hideSpines !== true && self.spines.length > 0){
				spine_inner_width = $(self.spines[0]).height();
				spine_outer_width = $(self.spines[0]).outerHeight();
			}
            
			slide_width = width - spine_outer_width*self.spines.length;
            if(self.options.hideSpines === true){
                slide_width = width;
            }
            
			spine_half_width = Math.ceil(spine_inner_width/2);
        };
        
        
		var initialize = function(opts){
			if((self.browser.opera && self.browser.version < "10.5") || self.browser.msie6 || self.browser.firefox2 || self.browser.firefox30){
				if(typeof(console) != "undefined"){
					if(typeof(console.error) == "function"){
						console.error("This web browser is not supported by SlideDeck. Please view this page in a modern, CSS3 capable browser or a current version of Inernet Explorer");
					}
				}
				return false;
			}
            
            if(typeof(opts) != "undefined"){
				for(var key in opts){
					self.options[key] = opts[key];
				}
			}
			if(self.spines.length < 1){
				self.options.hideSpines = true;
			}
			if(self.options.hideSpines === true){
				self.options.activeCorner = false;
			}
		
			self.current = Math.min(self.slides.length,Math.max(1,self.options.start));
            
            if(el.height() > 0){
                setupDimensions();
                buildDeck();
            } else {
                var startupTimer;
                startupTimer = setTimeout(function(){
                    setupDimensions();
                    if(el.height() > 0){
                        clearInterval(startupTimer);
                        setupDimensions();
                        buildDeck();
                    }
                }, 20);
            }
		};
        
        
        var loaded = function(func){
            var thisTimer;
            thisTimer = setInterval(function(){
                if(self.isLoaded == true){
                    clearInterval(thisTimer);
                    func();
                }
            }, 20);
        };
        
        
        this.loaded = function(func){
            loaded(func);
                        
            return self;
        };
		
		
		this.next = function(params){
			var nextSlide = Math.min(self.slides.length,(self.current + 1));
			if(self.options.cycle === true){
				if(self.current + 1 > self.slides.length){
					nextSlide = 1;
				}
			}
			slide(nextSlide,params);
			return self;
		};
		
		this.prev = function(params){
			var prevSlide = Math.max(1,(self.current - 1));
			if(self.options.cycle === true){
				if(self.current - 1 < 1){
					prevSlide = self.slides.length;
				}
			}
			slide(prevSlide,params);
			return self;
		};
		
		this.goTo = function(ind,params){
			self.pauseAutoPlay = true;
			slide(Math.min(self.slides.length,Math.max(1,ind)),params);
			return self;
		};
		
        this.setOption = function(opts,val){
            setOption(opts,val);
            return self;
        };
		
		initialize(opts);
	};
	
	$.fn.slidedeck = function(opts){
		var returnArr = [];
		for(var i=0; i<this.length; i++){
			if(!this[i].slidedeck){
				this[i].slidedeck = new SlideDeck(this[i],opts);
			}
			returnArr.push(this[i].slidedeck);
		}
		return returnArr.length > 1 ? returnArr : returnArr[0];
	};
})(jQuery);